package cn.virens.common.simple;

import cn.hutool.core.util.StrUtil;
import cn.virens.common.exception.APIException;
import cn.virens.common.init.InitExecutorUtil;
import io.mybatis.provider.EntityTable;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Supplier;

public class DynamicTableNameLocal extends InheritableThreadLocal<Map<String, Supplier<String>>> {
    @Override
    protected Map<String, Supplier<String>> childValue(Map<String, Supplier<String>> parentValue) {
        return parentValue != null ? new HashMap<>(parentValue) : null;
    }

    @Override
    protected Map<String, Supplier<String>> initialValue() throws APIException {
        Map<String, Supplier<String>> answer = new HashMap<>();
        answer.put("{month}", InitExecutorUtil::mon);
        answer.put("{year}", InitExecutorUtil::year);

        return answer;
    }

    public String generateDynamic(EntityTable entity) throws APIException {
        return generateDynamicTableName(entity.table());
    }

    /**
     * 设置动态表名变量(当前线程/子线程有效)
     *
     * @param key      关键词
     * @param supplier 供应者
     */
    public Object variable(String key, Supplier<String> supplier) {
        return get().put(k(key), supplier);
    }

    /**
     * 设置动态表名变量(当前线程/子线程有效)
     *
     * @param key   关键词
     * @param value 替换值
     */
    public Object variable(String key, String value) {
        return get().put(k(key), () -> value);
    }

    /**
     * 执行内容替换动作
     *
     * @param table 表名
     * @param entry 替换规则
     * @return 替换后的表名
     */
    private String replace(String table, Entry<String, Supplier<String>> entry) {
        return StrUtil.replace(table, entry.getKey(), entry.getValue().get());
    }

    /**
     * 遍历替换待处理的表名内容
     *
     * @param table 表名
     * @return 替换后的表名
     * @throws APIException 普通异常
     */
    private String generateDynamicTableName(String table) throws APIException {
        for (Entry<String, Supplier<String>> entry : get().entrySet()) {
            if (StrUtil.contains(table, entry.getKey())) {
                table = replace(table, entry);
            }
        }

        return table;
    }

    /**
     * 将KEY进行预处理
     *
     * @param k 变量名称
     * @return 处理后的变量规则
     */
    private String k(String k) {
        return "{" + k + "}";
    }

}
